package net.wangds.common;

import net.wangds.common.factory.Filter;
import net.wangds.common.factory.ProviderFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 基础对象类.
 * <p>
 * 该类是对{@link java.lang.Object}的扩展.目前扩展的功能只有日志接口.
 * </p>
 * <p>
 * 修改列表:
 * <ol>
 * <li>补充注释. wangds@gmail.com 2013-10-13 00:10</li>
 * <li>根据Check Style提示更改类名, by wangds@gmail.com 2013-10-13 00:10</li>
 * </ol>
 * </p>
 * 
 * @author wangds@gmail.com
 * @version 0.1.1
 * @since 0.1
 */
public class GeneralParentObject implements Component {

  /**
   * 获得日志对象.
   * 
   * @return 日志对象.
   */
  protected final Logger getLogger() {
    final Class<? extends GeneralParentObject> clz = this.getClass();
    return LoggerFactory.getLogger(clz);
  }

  /**
   * 获得静态块或方法中能够使用的日志对象.
   * 
   * @param clz
   *          调用日志的类的类型.
   * @return 日志对象.
   */
  public static final Logger staticLogger(final Class<?> clz) {
    Class<?> cls = null;
    if (clz == null) {
      cls = net.wangds.common.GeneralParentObject.class;
    } else {
      cls = clz;
    }
    return LoggerFactory.getLogger(cls);
  }

  protected <E extends Throwable> void testNeedAnException() throws E {
  }

  @SuppressWarnings({ "unchecked", "rawtypes" })
  protected <T> T getGenericInstance(
      String genericTypeName, Filter<T> filter, Object ... constructorArgs) {
    T res = null;
    Type superClass = this.getClass().getGenericSuperclass();
    ParameterizedType paramType = (ParameterizedType) superClass;

    Type[] types = paramType.getActualTypeArguments();
    for (Type cur : types) {
      if (cur.getTypeName().equals(genericTypeName)) {
        Class<T> clz = (Class<T>)cur;
        if (Modifier.isAbstract(clz.getModifiers()) || clz.isInterface()) {
          res = ProviderFactory.getInstance(clz, filter);
        } else {
          int len = constructorArgs.length;
          Class[] argsClzes = new Class[len];
          for (int i = 0; i < len; i++) {
            argsClzes[i] = constructorArgs[i].getClass();
          }
          try {
            res = (T)clz.getConstructor(argsClzes).newInstance(constructorArgs);
          } catch (InstantiationException
              | IllegalAccessException
              | IllegalArgumentException
              | InvocationTargetException
              | NoSuchMethodException
              | SecurityException e) {
            this.getLogger().error(e.getLocalizedMessage(),e);
          }
        }
      }
    }
    return res;
  }
}
